import json
import os


def _load_json(path: str) -> dict:
    if not os.path.exists(path):
        raise FileNotFoundError(f'配置文件不存在: {path}')
    with open(path, 'r', encoding='utf-8') as f:
        return json.load(f)


def load_common_config(path: str) -> dict:
    cfg = _load_json(path)
    # 基础校验：字段必须带desc与type
    tp = cfg.get('terminal_phone')
    if not tp or 'desc' not in tp or 'type' not in tp:
        raise ValueError('common.json: terminal_phone 必须包含 desc 与 type')
    return cfg


def load_frame_config(path: str) -> dict:
    cfg = _load_json(path)

    # 引用机制：当存在ref时，从指定版本路径加载目标命令定义
    ref = cfg.get('ref')
    if isinstance(ref, dict) and all(k in ref for k in ('standard', 'edition', 'cmd')):
        # 从当前路径向上找到frames目录
        current_dir = os.path.dirname(path)
        frames_root = current_dir
        # 向上查找直到找到frames目录
        while os.path.basename(frames_root) != 'frames' and frames_root != os.path.dirname(frames_root):
            frames_root = os.path.dirname(frames_root)
        
        # 如果没找到frames目录，使用当前目录的父目录
        if os.path.basename(frames_root) != 'frames':
            frames_root = os.path.dirname(current_dir)
            
        target = os.path.join(frames_root, ref['standard'], ref['edition'], f"{str(ref['cmd']).lower()}.json")
        if not os.path.exists(target):
            raise FileNotFoundError(f"ref 目标不存在: {target}")
        cfg = _load_json(target)
    config_type = str(cfg.get('type', '')).upper()
    
    if config_type == 'STRUCT':
        # STRUCT 类型：需要 fields 数组（允许为空，用于空消息体）
        fields = cfg.get('fields', [])
        if not isinstance(fields, list):
            raise ValueError('STRUCT 需要 fields 数组')
        if fields:  # 只有当 fields 非空时才检查 order
            orders = [int(f['order']) for f in fields if 'order' in f]
            if len(orders) != len(fields) or len(set(orders)) != len(orders):
                raise ValueError('STRUCT 字段 order 必须唯一且完整')
            
    elif config_type == 'MAP':
        # MAP 类型：需要 keyFixedLen, valueLenPrefix, entries
        if 'keyFixedLen' not in cfg or 'valueLenPrefix' not in cfg or 'entries' not in cfg:
            raise ValueError('MAP 需要 keyFixedLen, valueLenPrefix, entries')
        if not isinstance(cfg['entries'], list):
            raise ValueError('MAP entries 必须为数组')
            
    elif config_type == 'ARRAY':
        # ARRAY 类型：需要 items 数组
        items = cfg.get('items', [])
        if not isinstance(items, list):
            raise ValueError('ARRAY 需要 items 数组')
            
    elif config_type in ['BYTE', 'WORD', 'DWORD', 'QWORD', 'BCD', 'STRING', 'BYTES', 'BITFIELD', 'FLOAT', 'DOUBLE']:
        # 基本类型：需要 value 字段
        if 'value' not in cfg:
            raise ValueError(f'{config_type} 需要 value 字段')
        
        # BYTES 类型特殊处理：检查 ascii 和 padding 配置
        if config_type == 'BYTES':
            ascii_mode = cfg.get('ascii', False)
            if not isinstance(ascii_mode, bool):
                raise ValueError('BYTES ascii 配置必须是布尔值')
            
            padding = cfg.get('padding', 0x00)
            if not isinstance(padding, int) or padding < 0 or padding > 255:
                raise ValueError('BYTES padding 配置必须是0-255的整数')
            
    else:
        raise ValueError(f'不支持的配置类型: {config_type}。支持的类型: STRUCT, MAP, ARRAY, BYTE, WORD, DWORD, QWORD, BCD, STRING, BYTES, BITFIELD, FLOAT, DOUBLE')
    
    return cfg




